package dao;

import utils.DButils;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.util.ArrayList;
import java.util.List;

public class BaseDao {
    public boolean update(String sql,Object...args){  //对数据库增删改方法  成功则返回TRUE反之FALSE
        Connection connection=null;
        PreparedStatement preparedStatement=null;
        try {
            connection= DButils.getConnection();//获取连接对象
            preparedStatement=connection.prepareStatement(sql);//构造SQL语句
            for (int i = 0; i < args.length ; i++) {
                preparedStatement.setObject(i+1,args[i]);//为占位符赋值
            }
            if(preparedStatement.executeUpdate()>0){//执行SQL语句
                return true; //执行,并且有结果,则返回TRUE
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            DButils.close(connection,preparedStatement,null);//关闭资源,因为是增删改方法,所以没有使用到ResuLtset,所以其为空
        }
        return false;//被捕获异常,则代表执行出现问题,FALSE;
    }
    public <T> T getInstance(Class<T> clazz,String sql,Object...args){  //对数据库的查询方法,使用泛型是为了通用,能对所以的表进行查询
        Connection connection=null;  //连接对象
        PreparedStatement preparedStatement=null; //构造SQL语句
        ResultSet resultSet=null;  //查询到的结果集
        T instance=null;  //要返回的泛型对象,依据传入的参数来定
        try {
            connection=DButils.getConnection(); //获取数据库连接对象
            preparedStatement=connection.prepareStatement(sql);  //构造SQL语句
            for (int i = 0; i <args.length ; i++) {
                preparedStatement.setObject(i+1,args[i]);//为占位符赋值
            }
            resultSet= preparedStatement.executeQuery();//获取查询结果的集和

            if (resultSet.next()){  //next后光标下移,看有没有数据,有则拿出.没有则退出
                //利用反射构造对象,
                Constructor constructor= clazz.getDeclaredConstructor();
                instance=(T) constructor.newInstance();
                ResultSetMetaData rsmd=resultSet.getMetaData();
                for (int i = 0; i < rsmd.getColumnCount(); i++) {
                    String columnName=rsmd.getColumnLabel(i+1);
                    Object columnValue=resultSet.getObject(i+1);
                    Field field=clazz.getDeclaredField(columnName);
                    field.setAccessible(true);
                    field.set(instance,columnValue);
                }
                return instance;  //有则返回得到的结果集
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            DButils.close(connection,preparedStatement,resultSet);//关闭资源
        }
        return null;//没有结果则返回空
    }
    public <T> List<T> getList(Class<T> clazz, String sql, Object...args){  //查询多个信息的方法
        Connection connection=null;
        PreparedStatement preparedStatement=null;
        ResultSet resultSet=null;                   //同理
        List<T> list=new ArrayList<>(); //查询到的多个结果集合
        T instance=null;
        try{
            connection=DButils.getConnection();
            preparedStatement=connection.prepareStatement(sql);//执行SQL语句,并且得到resultset类,里面存放了你查到的数据--->可以想像为一张表,只是要怎么拿出表中的数据
            for (int i = 0; i < args.length; i++) {
                preparedStatement.setObject(i+1,args[i]);  //为占位符赋值
            }
            resultSet=preparedStatement.executeQuery();
            while(resultSet.next()){
                //利用反射构造对象
                Constructor<T> constructor=clazz.getDeclaredConstructor();
                instance=constructor.newInstance();
                ResultSetMetaData rsmd=resultSet.getMetaData();
                for (int i = 0; i < rsmd.getColumnCount(); i++) {
                    String columnName=rsmd.getColumnLabel(i+1);
                    Object columnValue=resultSet.getObject(i+1);
                    Field field=clazz.getDeclaredField(columnName);
                    field.setAccessible(true);
                    field.set(instance,columnValue);
                }
                list.add(instance);
            }
            return list;
        }
        catch (Exception e){
            e.printStackTrace();
        }
        finally {
            DButils.close(connection,preparedStatement,resultSet);  //关闭资源
        }
        return null;
    }
}
